<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/5/29 0029
 * Time: 22:04
 */

namespace console\controllers;

use app\models\ArcAndroid;
use app\models\ArcClassify;
use app\models\ArcProgress;
use app\models\ArcTrain;
use app\models\ThingRecordFile;
use common\helps\ClassifySearch;
use common\helps\Foo;
use common\helps\Tools;
use Yii;
use yii\console\Controller;
class DosomethingController extends Controller
{
    static $aa;
    static $bb;
    static $process;

    public function actionIndex($a, $b)
    {
        DosomethingController::$aa = $a;
        DosomethingController::$bb = $b;
//        $redirect_stdout  = true;
//        DosomethingController::$process = new \Swoole\Process('console\controllers\callback_function',$redirect_stdout);
//        DosomethingController::$process->start();
//    }
//
//}
//function callback_function (){
//    swoole_timer_after(1, function () {
        $parms = json_decode(DosomethingController::$bb);
        $arcProgressModel = saveToSql("", $parms);
        $res = shell_exec(DosomethingController::$aa);
        //$resArr = Tools::baiduresultToArray($res);//拿到了结果，然后存入数据库
        $resArr = Tools::aliyunresultToArray($res);//拿到了结果，然后存入数据库
        $resStr = json_encode($resArr);//将得到的数组转化为json字符串
        if (file_exists($parms->tempPath)) unlink($parms->tempPath);
        updateToSql($resStr, $parms, $arcProgressModel);
//    });
    }
}

function saveToSql($resStr, $parms)
{
    //开启事务
    $arcTrainModel = ArcTrain::findOne($parms->arc_train);
    $arcAndroidModel = ArcAndroid::findOne($arcTrainModel->arc_android);
    if ($arcTrainModel->progress == 3) {//如果是中止了，就需要停止
        exit();
    }
    if ($arcTrainModel->progress_num >= $arcAndroidModel->onetime_num) {//如果是中止了，就需要停止
        //查到此条机器人，更新相应的参数，训练的数据数加1
        $arcTrainModel->updateAttributes(['progress' => 2]);//更新arc_train的progress_num新增1
        stopPid();
        exit();
    }
    $arcProgressModel = new ArcProgress();
    $arcProgressModel->arc_language = $resStr;
    $arcProgressModel->progress = 1;
    $arcProgressModel->thing_recordfile = $parms->thing_recordfile;
    $arcProgressModel->arc_train = $parms->arc_train;
    $arcProgressModel->arc_classify = $parms->arc_classify;
    $arcProgressModel->create_time = time();
//    $arcProgressModel->ip = Tools::getip();
    $arcProgressModel->save();//更新识别的结果，识别完成
    $lastId = \Yii::$app->getDb()->getLastInsertID();
    return ArcProgress::findOne($lastId);
};

function updateToSql($resStr, $parms,$arcProgressModel)
{
    //开启事务
    $arcTrainModel = ArcTrain::findOne($parms->arc_train);
    $arcAndroidModel = ArcAndroid::findOne($arcTrainModel->arc_android);
    if ($arcTrainModel->progress_num >= $arcAndroidModel->onetime_num) {//如果是中止了，就需要停止
        //查到此条机器人，更新相应的参数，训练的数据数加1
        $arcTrainModel->updateAttributes(['progress' => 2]);//更新arc_train的progress_num新增1
        stopPid();
        exit();
    }
    $arcProgressModel->updateAttributes(['arc_language' => $resStr, 'progress' => $parms->progress]);//更新arc_train的progress_num新增1
    if ($arcTrainModel->progress == 3) {//如果是中止了，就需要停止
        $arcTrainModel->updateAttributes(['progress_num' => $arcTrainModel->progress_num + 1, 'update_time' => time()]);
        stopPid();
        exit();
    }
    $classifySearch = new ClassifySearch();
    $arc_classify_status = $classifySearch->search_classify($parms->arc_classify, $resStr);
    $arcProgressModel->updateAttributes(['arc_classify_status' => $arc_classify_status]);
    //查到此条机器人，更新相应的参数，训练的数据数加1
    $arcTrainModel->updateAttributes(['progress_num' => $arcTrainModel->progress_num + 1, 'progress' => 1, 'update_time' => time()]);//更新arc_train的progress_num新增1
    /* 以下是训练的方法 */
    classifyContinue($arcTrainModel->id, $arcTrainModel->progress_num, $arcAndroidModel->onetime_num);
};

function stopPid(){
//    DosomethingController::$process->exit();
}

/**
 * 根据模型以及机器人种类来进行相应的继续文件分类等操作
 */
function classifyContinue($arcTrainId, $arcTrainProgressNum, $onetimeNum)
{
    try {
        $arcTrainModel = new ArcTrain();
        $arcClassifyModel = new ArcClassify();
        $arcAndroidModel = new ArcAndroid();
        $arcProgressModel = new ArcProgress();
        $arcTrain = ArcTrain::findOne($arcTrainId);
        $sql = 'select count(*) from '
            . $arcTrainModel->tableName() . ' where arc_android='
            . $arcTrain->arc_android;//得到当前某个机器人已经使用的数量
        $number = $arcTrainModel->getDb()->createCommand($sql)->queryScalar();//得到该机器人现在的总数量
        $arc_android = $arcAndroidModel->findOne($arcTrain->arc_android);//得到该机器人
        $onetimeNum = $arc_android->onetime_num;//得到该机器人的一次可以训练的机器人数量，默认是500
        if ($number <= $arc_android->number) {//数量比较小，小于规定的要求
            //1，首先添加一条训练表
            $arcTrainModel = $arcTrainModel->findOne($arcTrainId);
            if ($arcTrainModel->progress == 1) {//表示的是继续训练,设置progress为1，未训练为0，正在训练为1，已经训练完成为2,4为文件不存在
                if (0 <= $arcTrainModel->progress_num && $arcTrainModel->progress_num < $onetimeNum) {//进行默认500次的循环，每次都会发送本次拿到的语音文件到阿里云后台去进行识别
                    // 然后是将该进度表保存到arc_progress表
                    $thingRecordFileModel = new ThingRecordFile();
                    //如果是progress==1就表明正在进行识别，此处就拿到这个作为最新的id
                    $newest = $arcProgressModel->find()->where('progress != 0')->orderBy('id desc')->one();
                    $newestId = isset($newest->thing_recordfile) ? $newest->thing_recordfile : 0;
                    //取最近的未训练的的录音文件，然后将该录音文件进行相应的识别分类
                    $thingRecordFile = $thingRecordFileModel->find()->where('ID > ' . $newestId)->one();
                    if (empty($thingRecordFile)) {//已经识别完成，退出，让状态变成2
                        $arcProgressModel->updateAttributes(['arc_progress' => 2]);
                        stopPid();
                        exit();
                    }
                    //未完成
                    $parms = json_decode('' . str_replace('\'', '"', $arc_android->parms));
                    if (empty($parms)) {//参数为空，错误
                        stopPid();
                        exit();
                    }
                    //本地语音文件的路径
                    $filePath = $thingRecordFile->Filepath;
                    //linux下用getFilePath
                    //windows系统下用getFilePathWindows
                    $filePath = Tools::getFilePath($filePath);
                    /************************************** 此处很重要 要修改为相对应的域名
                     ***************************************************/
                    $httpFilePath = Tools::getUrlFilePath($filePath);
                    //linux下用./
                    $filePath1 = "." . $filePath;
                    //windows下用
                    $filePath2 = $filePath;
                    if (!file_exists($filePath1)) {
                        Tools::httpcopy($httpFilePath, $filePath1);
                    }
                    if (file_exists($filePath1)) {
                        $parmsArr['progress'] = 2;
                    } else {
                        $parmsArr['progress'] = 4;
                    }
                    $parmsArr['thing_recordfile'] = $thingRecordFile->ID;
                    $parmsArr['arc_train'] = $arcTrainModel->id;
                    $parmsArr['arc_classify'] = $arcTrainModel->arc_classify;
                    $parmsArr['arc_progress'] = $newest->id;
                    //百度云下用actionArcOneSync
                    //阿里云下用actionArcOneSyncWindows
//                            actionArcOneSyncBaidu($filePath,$parmsArr);
                    actionArcOneSyncAli($filePath1, $parmsArr);
                } else {//训练完成
                    $arcTrainModel->updateAttributes(['progress' => 2]);
                    stopPid();
                    exit();
                }
            } else if ($arcTrainModel->progress == 2) {//表示的意思是训练完成
                stopPid();
                exit();
            } else if ($arcTrainModel->progress == 3) {//表示的意思是中止
                stopPid();
                exit();
            }
        }
    } catch (\Exception $exception) {
        var_dump($exception);
        stopPid();
        exit();
    }
}

/**
 * 公共的非异步Windows
 * @return string
 */
function actionArcOneSyncAli($filepath, $parms, $arcTrainModel = null)
{
    if (file_exists($filepath)) {
        $baseName = basename($filepath);
        $tempPath = "./temp/" . $baseName;
        exec("java -jar ./asr/windows/Wav2Wav.jar " . $filepath . " " . $tempPath);
        $arc_train = ArcTrain::findOne($parms['arc_train']);
        $arc_android = $arc_train->arc_android;
        $arc_android_parms = ArcAndroid::findOne($arc_android)->parms;
        $arc_android_parms = str_replace("'", "\"", $arc_android_parms);
        $arc_android_arr = json_decode($arc_android_parms);
        $appKey = $arc_android_arr->appKey;
        $akId = $arc_android_arr->akId;
        $akSecret = $arc_android_arr->akSecret;
        $toCparms = $appKey . " " . $akId . " " . $akSecret . " " . $tempPath;
        $command1 = "java -jar ./asr/windows/asr.jar " . $toCparms;
        $command1 = str_replace('\\', '/', $command1);
        $parms['tempPath'] = $tempPath;
        $foo = new Foo();
        $foo->fooAliContinue($command1, $parms, $arcTrainModel);
    } else {
        saveToSql("", $parms);
    }
}
